<?php
/**
 * Miffos framework
 * ----------------------------------------------
 *
 * Copyright (c) 2008, 2009 Martin Sadový (http://sodae.cz)
 *
 * This source file is subject to the "Miffos license" that is bundled
 * with this package in the file license.txt.
 *
 * @copyright  Copyright (c) 2008, 2009 Martin Sadový
 * @license    license.txt
 * @link       http://miffos.sodae.cz
 * @package    miffos
 * @version    $Id$
 */


class FileCache{
  
    private $namespace;

    public function __construct($namespace)
    {
       $this->namespace = $namespace;
    }
    


    /**
     * Get cache data
     * @param string $name
     * @return string or null
     */
    public function get($name)
    {
        $data = $this->openCache();
        
        if($data === NULL)
           return null;
        
        if(!$this->verify($data)){
           $this->remove();
           return null;
        }
        
           
        return $data['data'][$name];
        
    }
    
    

    /**
     * Set cache data
     * @param string $name
     * @param string $value
     */
    public function set($name, $value)
    {
        $this->editCache(array(array('data', $name , $value)) );
    }
    
    

    /**
     * Remove data
     * @param string or null $name
     * @return void
     */
    public function remove($name = null)
    {
        if( !is_null($name) )
           return $this->editCache(array( array('data', $name , null) ));
           
        if(file_exists(Cache::$dir.$this->generationFileName()))
            @unlink(Cache::$dir.$this->generationFileName());
    }
    
    

    /**
     * Set expire time
     * @param int $expire
     */
    public function expire($expire)
    {
        $this->editCache(array('meta', 'expire' , $expire+time() ) );
    }
    
    

    /**
     * Verify cache
     * @param array $cache
     * @return bool
     */
    private function verify(array $cache)
    {    
        if($cache['meta']['expire'] <= time() AND $cache['meta']['expire'] != 0 )
           return false;
           
        return true;
    }
    


    /**
     * Set data in cache
     * @param array $array
     */
    private function editCache(array $array)
    {
        $data = $this->openCache();
        
        if($data === NULL)
            $data = array('meta' => array('expire'=>0),
                          'data' => array() );
                          
        foreach($array as $d )
            $data[$d[0]][$d[1]] = $d[2];

        $serialize = $this->serialize($data['meta'], $data['data']);
        file_put_contents(Cache::$dir.$this->generationFileName(), $serialize);
    }
    


    /**
     * Open cache file and unserialize
     * @return array
     */
    private function openCache()
    {
        $filename = ( Cache::$dir.$this->generationFileName() );
        if(!file_exists($filename) )
           return NULL;
        
        $data = file_get_contents($filename);
        return $this->unserialize($data);
    }
    
    

    /**
     * Unserialize cache data
     * @param string $content
     * @return array
     */
    private function unserialize($content)
    {
        $data = array('meta' => array(),
                      'data' => null );
                      
        preg_match('#^\<\?php \/\/ cache\[(\d+)\](.*)#', $content, $matches);
        
        $strHead = strlen('<?php // cache['.$matches[1].']');
        
        $Udata = substr($content, $strHead+((int) $matches[1]) );
        $Umeta = substr($content, $strHead, -strlen($Udata) );
        
        $data['data'] = unserialize($Udata);
        $data['meta'] = unserialize($Umeta);
        
        return $data;
    }
    
    

    /**
     * Snserialize cache data
     * @param array $meta
     * @param mixed $data
     * @return array
     */
    private function serialize(array $meta, $data)
    {
        $meta = serialize($meta);
        $head = '<?php // cache['.strlen($meta).']';
        $serialize = $head.$meta.serialize($data);
        return $serialize;
    }
    
    

    /**
     * Generation filename for cache
     * @return string
     */
    private function generationFileName()
    {
        return 'cache-'.md5($this->namespace).'.php';
    }

}

?>